﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using YJ.JobSchedule.Configuration;
using YJ.JobSchedule.Unit;
using YJ.Utilities.Json;
using System.IO;

namespace YJ.JobService
{
    public partial class ConfigForm : Form
    {

        private string jobKey;
        private MainForm mainForm;
        JobConfiguration jobConfig;

        public ConfigForm(string jobKey, MainForm mainForm)
        {
            this.mainForm = mainForm;
            this.jobKey = jobKey;
            InitializeComponent();

            Init();
        }

        private async Task Init()
        {
            jobConfig = await JobConfiguationManager.GetJobConfigurationByKeyAsync(jobKey);
            this.Text = string.Format("配置【{0}:{1}】执行计划", jobConfig.JobKey, jobConfig.Name);
            cbxInDayIntervalType.SelectedIndex = 0;
            if (jobConfig.Schedule == null)
                return;

            Action initInDay = () =>
            {
                if (jobConfig.Schedule.InDay != null)
                {
                    if (jobConfig.Schedule.InDay.UnitType == UnitInDayType.recurring)
                    {
                        radioIndayRecurring.Checked = true;
                        if (jobConfig.Schedule.InDay.Interval != null)
                        {
                            numberIndayInterval.Value = jobConfig.Schedule.InDay.Interval.Interval;
                            cbxInDayIntervalType.SelectedIndex = jobConfig.Schedule.InDay.Interval.IntervalType == IntervalUnitType.hour ? 0 : (
                                                jobConfig.Schedule.InDay.Interval.IntervalType == IntervalUnitType.minute ? 1 : 2);
                        }

                        if (jobConfig.Schedule.InDay.DayTimeRangeUnit != null && jobConfig.Schedule.InDay.DayTimeRangeUnit.StartTime != null)
                        {
                            var now = DateTime.Now;
                            timeInDayRecurringStart.Checked = true;
                            timeInDayRecurringStart.Value = new DateTime(now.Year, now.Month, now.Day,
                                jobConfig.Schedule.InDay.DayTimeRangeUnit.StartTime.Hour,
                                jobConfig.Schedule.InDay.DayTimeRangeUnit.StartTime.Minute,
                                jobConfig.Schedule.InDay.DayTimeRangeUnit.StartTime.Second);
                        }
                        if (jobConfig.Schedule.InDay.DayTimeRangeUnit != null && jobConfig.Schedule.InDay.DayTimeRangeUnit.EndTime != null)
                        {
                            var now = DateTime.Now;
                            timeInDayRecurringEnd.Checked = true;
                            timeInDayRecurringEnd.Value = new DateTime(now.Year, now.Month, now.Day,
                                jobConfig.Schedule.InDay.DayTimeRangeUnit.EndTime.Hour,
                                jobConfig.Schedule.InDay.DayTimeRangeUnit.EndTime.Minute,
                                jobConfig.Schedule.InDay.DayTimeRangeUnit.EndTime.Second);
                        }
                    }
                    else
                    {
                        radioIndaySpecific.Checked = true;
                        if (jobConfig.Schedule.InDay.SpecificTimes != null)
                        {
                            jobConfig.Schedule.InDay.SpecificTimes.ForEach(r =>
                            {
                                lsbIndaySpecificTime.Items.Add(r.ToString());
                            });
                        }
                    }
                }

                if (jobConfig.Schedule.StartTime != null)
                {
                    datetimeStart.Checked = true;
                    datetimeStart.Value = jobConfig.Schedule.StartTime.Value;
                }
                if (jobConfig.Schedule.EndTime != null)
                {
                    datetimeEnd.Checked = true;
                    datetimeEnd.Value = jobConfig.Schedule.EndTime.Value;
                }
            };


            if (jobConfig.Schedule.Type == ScheduleType.SpecificDateTimes)
            {
                radioSpecificDateTime.Checked = true;
                if (jobConfig.Schedule.SpecificTimes != null)
                {
                    jobConfig.Schedule.SpecificTimes.ForEach(r =>
                    {
                        lsbSpecificTimes.Items.Add(r.ToStringyyyyMMddHHmmss());
                    });
                }
                return;
            }

            else if (jobConfig.Schedule.Type == ScheduleType.EveryDays)
            {
                radioDay.Checked = true;

                numericDay.Value = jobConfig.Schedule.Interval ?? 1;

                initInDay();
            }

            else if (jobConfig.Schedule.Type == ScheduleType.EveryWeeks)
            {
                radioWeek.Checked = true;
                numericWeek.Value = jobConfig.Schedule.Interval ?? 1;

                if (jobConfig.Schedule.SpecificDayOfWeeks != null && jobConfig.Schedule.SpecificDayOfWeeks.Count > 0)
                {
                    foreach (Control item in gbWeek.Controls)
                    {
                        if (item.Name.Contains("cbxweek") && jobConfig.Schedule.SpecificDayOfWeeks.Contains((DayOfWeek)item.Tag.ToString().ConvertTo<int>()))
                        {
                            (item as CheckBox).Checked = true;
                        }
                    }
                }
                initInDay();
            }

            else if (jobConfig.Schedule.Type == ScheduleType.EveryMonths)
            {
                radioMonth.Checked = true;
                numericMonth.Value = jobConfig.Schedule.Interval ?? 1;

                if (jobConfig.Schedule.SpecificDayOfMonths != null && jobConfig.Schedule.SpecificDayOfMonths.Count > 0)
                {
                    foreach (Control item in gbMonth.Controls)
                    {
                        if (item.Name.Contains("cbxMonthDay") && jobConfig.Schedule.SpecificDayOfMonths.Contains(item.Text.ConvertTo<int>()))
                        {
                            (item as CheckBox).Checked = true;
                        }
                    }
                }
                initInDay();
            }

            else if (jobConfig.Schedule.Type == ScheduleType.EveryYears)
            {
                radioYear.Checked = true;
                numericYear.Value = jobConfig.Schedule.Interval ?? 1;

                if (jobConfig.Schedule.SpecificMonthOfYears != null && jobConfig.Schedule.SpecificMonthOfYears.Count > 0)
                {
                    foreach (Control item in gbYearMonth.Controls)
                    {
                        if (item.Name.Contains("cbxYearMonth") && jobConfig.Schedule.SpecificMonthOfYears.Contains(item.Text.ConvertTo<int>()))
                        {
                            (item as CheckBox).Checked = true;
                        }
                    }
                }
                if (jobConfig.Schedule.SpecificDayOfMonthInYears != null && jobConfig.Schedule.SpecificDayOfMonthInYears.Count > 0)
                {
                    foreach (Control item in gbYearDay.Controls)
                    {
                        if (item.Name.Contains("cbxYearMonthDay") && jobConfig.Schedule.SpecificDayOfMonthInYears.Contains(item.Text.ConvertTo<int>()))
                        {
                            (item as CheckBox).Checked = true;
                        }
                    }
                }
                initInDay();
            }

        }

        private ScheduleConfiguration CreateConfig()
        {
            #region inday

            Func<ScheduleInDay> getInday = () =>
             {
                 ScheduleInDay inday = new ScheduleInDay();
                 if (radioIndayRecurring.Checked)
                 {
                     inday.UnitType = UnitInDayType.recurring;
                     inday.Interval = new IntervalUnit();
                     inday.Interval.Interval = (int)numberIndayInterval.Value;
                     inday.Interval.IntervalType = cbxInDayIntervalType.SelectedIndex == 0
                         ? IntervalUnitType.hour
                         : (cbxInDayIntervalType.SelectedIndex == 1 ? IntervalUnitType.minute : IntervalUnitType.second);

                     inday.DayTimeRangeUnit = new DayTimeRange();
                     if (timeInDayRecurringStart.Checked)
                     {
                         inday.DayTimeRangeUnit.StartTime = new TimeInDay(timeInDayRecurringStart.Value.Hour,
                             timeInDayRecurringStart.Value.Minute, timeInDayRecurringStart.Value.Second);
                     }
                     if (timeInDayRecurringEnd.Checked)
                     {
                         inday.DayTimeRangeUnit.EndTime = new TimeInDay(timeInDayRecurringEnd.Value.Hour,
                             timeInDayRecurringEnd.Value.Minute, timeInDayRecurringEnd.Value.Second);
                     }

                     if (inday.DayTimeRangeUnit.EndTime != null && inday.DayTimeRangeUnit.StartTime != null &&
                        inday.DayTimeRangeUnit.EndTime <= inday.DayTimeRangeUnit.StartTime)
                     {
                         MessageBox.Show("一天内的执行计划中:运行范围结束时间必须大于开始时间!");
                         return null;
                     }
                 }
                 if (radioIndaySpecific.Checked)
                 {
                     inday.UnitType = UnitInDayType.specific;
                     inday.SpecificTimes = new List<TimeInDay>();

                     foreach (string item in lsbIndaySpecificTime.Items)
                     {
                         string[] values = item.Split(':');
                         inday.SpecificTimes.Add(new TimeInDay(values[0].ConvertTo<int>(), values[1].ConvertTo<int>(), values[2].ConvertTo<int>()));
                     }
                 }

                 return inday;
             };

            #endregion

            ScheduleConfiguration config = new ScheduleConfiguration();

            Func<bool> setStartAndEnd = () =>
            {
                if (datetimeStart.Checked)
                    config.StartTime = datetimeStart.Value;
                if (datetimeEnd.Checked)
                    config.EndTime = datetimeEnd.Value;

                if (config.StartTime.HasValue && config.EndTime.HasValue && config.EndTime.Value <= config.StartTime.Value)
                {
                    MessageBox.Show("任务的开始时间必须小于结束时间!");
                    return false;
                }

                return true;
            };

            if (radioSpecificDateTime.Checked)
            {//指定时间运行
                config.Type = ScheduleType.SpecificDateTimes;
                config.SpecificTimes = new List<DateTime>();
                foreach (var item in lsbSpecificTimes.Items)
                {
                    config.SpecificTimes.Add(Convert.ToDateTime(item));
                }
            }

            else if (radioDay.Checked)
            {//每多少天
                config.Type = ScheduleType.EveryDays;
                config.Interval = (int)numericDay.Value;
                var inday = getInday();
                if (inday == null || !setStartAndEnd())
                    return null;
                config.InDay = inday;

            }

            else if (radioWeek.Checked)
            {//每多少周
                config.Type = ScheduleType.EveryWeeks;
                config.Interval = (int)numericWeek.Value;
                var inday = getInday();
                if (inday == null || !setStartAndEnd())
                    return null;
                config.InDay = inday;
                config.SpecificDayOfWeeks = new List<DayOfWeek>();
                foreach (Control item in gbWeek.Controls)
                {
                    var cbx = item as CheckBox;
                    if (cbx != null && cbx.Checked && item.Name.Contains("cbxweek"))
                    {
                        config.SpecificDayOfWeeks.Add((DayOfWeek)item.Tag.ToString().ConvertTo<int>());
                    }
                }
            }

            else if (radioMonth.Checked)
            {//每多少月
                config.Type = ScheduleType.EveryMonths;
                config.Interval = (int)numericMonth.Value;
                var inday = getInday();
                if (inday == null || !setStartAndEnd())
                    return null;
                config.InDay = inday;
                config.SpecificDayOfMonths = new List<int>();
                foreach (Control item in gbMonth.Controls)
                {
                    var cbx = item as CheckBox;
                    if (cbx != null && cbx.Checked && item.Name.Contains("cbxMonthDay"))
                    {
                        config.SpecificDayOfMonths.Add(item.Text.ConvertTo<int>());
                    }
                }
            }

            else if (radioYear.Checked)
            {//每多少年
                config.Type = ScheduleType.EveryYears;
                config.Interval = (int)numericYear.Value;
                var inday = getInday();
                if (inday == null || !setStartAndEnd())
                    return null;
                config.InDay = inday;
                config.SpecificDayOfMonthInYears = new List<int>();
                config.SpecificMonthOfYears = new List<int>();

                foreach (Control item in gbYearMonth.Controls)
                {
                    var cbx = item as CheckBox;
                    if (cbx != null && cbx.Checked && item.Name.Contains("cbxYearMonth"))
                    {
                        config.SpecificMonthOfYears.Add(item.Text.ConvertTo<int>());
                    }

                }
                foreach (Control item in gbYearDay.Controls)
                {
                    var cbx = item as CheckBox;
                    if (cbx != null && cbx.Checked && item.Name.Contains("cbxYearMonthDay"))
                    {
                        config.SpecificDayOfMonthInYears.Add(item.Text.ConvertTo<int>());
                    }
                }
            }

            return config;
        }

        #region 事件响应
        private void btnAddSpecificDateTime_Click(object sender, EventArgs e)
        {
            var value = datetimeSpecificTime.Value.ToStringyyyyMMddHHmmss();
            if (!lsbSpecificTimes.Items.Contains(value))
                lsbSpecificTimes.Items.Add(value);
        }

        private void btnIndayAddSpecificTime_Click(object sender, EventArgs e)
        {
            var value = timeInDaySpecific.Value.ToString("HH:mm:ss");
            if (!lsbIndaySpecificTime.Items.Contains(value))
                lsbIndaySpecificTime.Items.Add(value);
        }


        private void lsbSpecificTimes_DoubleClick(object sender, EventArgs e)
        {
            lsbSpecificTimes.Items.Remove(lsbSpecificTimes.SelectedItem);
        }

        private void lsbIndaySpecificTime_DoubleClick(object sender, EventArgs e)
        {
            lsbIndaySpecificTime.Items.Remove(lsbIndaySpecificTime.SelectedItem);
        }

        private async void btnSave_Click(object sender, EventArgs e)
        {
            var config = CreateConfig();
            if (config == null)
                return;
            jobConfig.Schedule = config;
            await mainForm.SaveJobConfiguration(jobConfig);
            mainForm.RefreshReflectionJobs();
            mainForm.RefreshWinservicesJobs();

            this.Close();
        }
        #endregion


    }
}
